// UpdatingThreads.cpp
//
#include "UpdatingThreads.h"

#include "VObjectGL.h"

#include <QList>

#include "TimedBlock.h"
#include "MemCheck.h"

using namespace IDS;
using namespace IDS::IDEAS::OpenGLView;


// --------------------------------------------------------------------------------------------
ObjectUpdaterThread::ObjectUpdaterThread(/*GraphicScene *s*/)
: QThread(),
  //scene(s),
  running(false),
  updating(false)
//  workingObject(NULL)
{}

// --------------------------------------------------------------------------------------------
ObjectUpdaterThread::~ObjectUpdaterThread()
{
	queue.clear();
}

// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::start()
{
	running = true;
	QThread::start();
}

// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::stop()
{
	//blockSignals(true);
	running = false;
	QThread::quit();
}

// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::enqueueUpdate(std::vector<VObjectGL *> &objs,double precision)
{
	mutex.lock();
	queue.clear();
	for(size_t i=0; i<objs.size(); ++i)
	{
		Request r;
		r.object    = objs[i];
		r.precision = precision;
		
		queue.enqueue(r);
	}
	mutex.unlock();
}



// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::enqueueUpdate(VObjectGL *object,double precision)
{
	//Request r;
	//r.id        = id;
	//r.type      = type;
	//r.precision = precision;
		
	Request r;
	r.object    = object;
	r.precision = precision;
	
	mutex.lock();
	for(QQueue<Request>::iterator it = queue.begin(); it != queue.end(); )
	{
		if(it->object == r.object)
			it = queue.erase(it);
		else
			++it;	
	}
	queue.enqueue(r);
	mutex.unlock();
}

// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::run()
{
	while(running)
	{
		mutex.lock();
		while( !opQueue.isEmpty() )
		{
			Operation o = opQueue.dequeue();
			//switch (o.operation)
			for(QList<Request>::iterator it = queue.begin(); it!=queue.end(); )
			{
				if(it->object == o.object)
					it = queue.erase(it);
				else
					++it;
			}

			//printf("%p\n",(o.object));
			delete o.object;
		}
		mutex.unlock();

		mutex.lock();
		if( !queue.isEmpty() )
		{
			Request t = queue.dequeue();
			//printf("Updating queue len: %d\n",queue.size() );
			mutex.unlock();

			//TimedBlock tb("...",NULL,true,false);
			//printf("Updating (%d,%d) %s\n", 
			//	t.object->getIdentifier().id,
			//	t.object->getIdentifier().type,
			//	t.object->getDescription().c_str());

			//float f = 0;
			//if( t.object->getGeometricType() == VObjectGL::Point )
			//	f = scene->getDrawPrecision();
			//else
			//	f = scene->getDesiredApprox();

			//if( fabs(f) > 0.0001 )
			{
				try
				{
					t.object->updateLOD(t.precision);

					updating = true;
				}
				catch(...)
				{}
				//postRefresh();
				//emit refreshView();
			}
		}
		else
		{
			//updating = false;

			mutex.unlock();
			usleep(1000);
		}
	}
}
// --------------------------------------------------------------------------------------------
//void ObjectUpdaterThread::postRefresh()
//{
//	if( !scene->isWaitingForRefresh() )
//	{
//		scene->setRefreshFlag();
//		printf("Refresh Posted\n");
//		emit refreshView();
//	}
//	//else
//	//	printf("Refresh Cached\n");
//}

// --------------------------------------------------------------------------------------------
void ObjectUpdaterThread::enqueueOperation(VObjectGL *obj, int op)
{
	Operation o;
	o.object    = obj;
	o.operation = op;
	
	mutex.lock();
	opQueue.enqueue(o);
	mutex.unlock();
}